package com.the475group.obd;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import android.bluetooth.BluetoothSocket;
import android.util.Log;

import com.the475group.obd.enums.OBDCommand;
import com.the475group.obd.impl.OBDGatherListener;
import com.the475group.obd.model.OBDInfo;

public class OBDGather implements Runnable {

	private ArrayList<OBDGatherListener> listeners;
	
	private BluetoothSocket socket;
	private long waitTime;
	private OBDCommand[] commands;
	
	private Thread thread;
	private boolean isRunning;
	private Object lock;
	
	private static final String TAG = "OBDGather";
	
	
	public OBDGather(BluetoothSocket socket, long waitTime, OBDCommand[] commands) {
		super();
		this.socket = socket;
		this.waitTime = waitTime;
		this.commands = commands;
		
		thread = new Thread(this);
		isRunning = false;
		lock = new Object();
		
		listeners = new ArrayList<OBDGatherListener>();
		//TODO: manage protocols
	}
	
	public void addListener(OBDGatherListener listener){
		listeners.add(listener);
	}
	
	public void start(){
		synchronized (lock) {
			isRunning = true;
			lock.notifyAll();
			try{
				thread.start();
			}catch (IllegalThreadStateException e){
				//already started
			}			
		}		
	}
	
	public void stop(){
		isRunning = false;
	}

	@Override
	public void run() {
		final OBDInfo info = new OBDInfo();
		while(true){
			if(isRunning){
				for(OBDCommand c : commands){
					double value = c.formatValue(request(c.getCode()));
					info.setValue(value);
					info.setCommand(c);
					for(OBDGatherListener listener : listeners){
						listener.onReceiveInfo(info);
					}
				}
				
				try {
					Thread.sleep(waitTime);
				} catch (InterruptedException e) {
					Log.e(TAG,"Error on wait");
					e.printStackTrace();
				}
				
			} else {
				synchronized (lock) {
					try {
						lock.wait();
					} catch (InterruptedException e) {
						Log.e(TAG, "unable to pause thread (run method)");
						e.printStackTrace();
					}
				}				
			}
		}
	}
	
	private String request(final String code){
		byte b = 0;
		StringBuilder res = new StringBuilder();
		OutputStream out = null;
		InputStream in = null;
		
		try {
			in = socket.getInputStream();
			out = socket.getOutputStream();
			
			//send request
			out.write((code+"\r").getBytes());
			out.flush();
			
			Thread.sleep(500); //HACK GOLDEN HAMMER
			
			//read response
			while ((char) (b = (byte) in.read()) != '>')
				if ((char) b != ' ')
					res.append((char) b);
			String temp = res.toString().trim();
			
			Log.d(TAG, "INFO RECEIVED: "+temp);
			return temp;			
		} catch (IOException e) {
			Log.e(TAG,"error on get obd info (method request)");
			e.printStackTrace();
			return null;
		} catch (InterruptedException e) {
			Log.e(TAG,"error on sleeping thread (method request)");
			e.printStackTrace();
			return null;
		}
		
	}
}


